{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 线性回归\n",
    "\n",
    "### 一、算法描述\n",
    "\n",
    "m个样本，每个样本n维特征对应一个输出：\n",
    "$$\n",
    "(x_1^{(0)}, x_2^{(0)}, ...x_n^{(0)}, y_0), (x_1^{(1)}, x_2^{(1)}, ...x_n^{(1)},y_1), ... (x_1^{(m)}, x_2^{(m)}, ...x_n^{(m)}, y_m)\n",
    "$$\n",
    "假设函数  $hθ(X)$  mx1的向量，$θ$  为nx1的向量，$X$  为mxn维的矩阵\n",
    "\n",
    "模型矩阵表达：\n",
    "$$\n",
    "h_\\mathbf{\\theta}(\\mathbf{X}) = \\mathbf{X\\theta}\n",
    "$$\n",
    "损失函数矩阵表达：\n",
    "$$\n",
    "J(\\mathbf\\theta) = \\frac{1}{2}(\\mathbf{X\\theta} - \\mathbf{Y})^T(\\mathbf{X\\theta} - \\mathbf{Y})\n",
    "$$\n",
    "\n",
    "### 二、模型求解\n",
    "\n",
    "对损失函数进行求解\n",
    "\n",
    "梯度下降，迭代更新公式：\n",
    "$$\n",
    "\\mathbf\\theta= \\mathbf\\theta - \\alpha\\mathbf{X}^T(\\mathbf{X\\theta} - \\mathbf{Y})\n",
    "$$\n",
    "最小二乘法，求得结果：\n",
    "$$\n",
    "\\mathbf{\\theta} = (\\mathbf{X^{T}X})^{-1}\\mathbf{X^{T}Y}\n",
    "$$\n",
    "\n",
    "### 三、线性回归推广\n",
    "\n",
    "#### 3.1 多项式回归-对特征推广\n",
    "\n",
    "线性回归模型，如果特征包含的二次方等项，此时模型就变为多项式回归。通过对多项式进行改进，变成线性回归。\n",
    "\n",
    "有2个特征的2次方多项式回归模型：\n",
    "$$\n",
    "h_\\theta(x_1, x_2) = \\theta_0 + \\theta_{1}x_1 + \\theta_{2}x_{2} + \\theta_{3}x_1^{2} + \\theta_{4}x_2^{2} + \\theta_{5}x_{1}x_2\n",
    "$$\n",
    "\n",
    "$$\n",
    "令 x_0 = 1, x_1 = x_1, x_2 = x_2, x_3 =x_1^{2}, x_4 = x_2^{2}, x_5 =  x_{1}x_2\n",
    "$$\n",
    "\n",
    "$$\n",
    "则可以写成h_\\theta(x_1, x_2) = \\theta_0 + \\theta_{1}x_1 + \\theta_{2}x_{2} + \\theta_{3}x_3 + \\theta_{4}x_4 + \\theta_{5}x_5\n",
    "$$\n",
    "\n",
    "#### 3.2 广义线性回归-对y推广\n",
    "\n",
    "$Y$不满足和$X$的线性关系，但是$lnY$ 和$X$满足线性关系：\n",
    "$$\n",
    "ln\\mathbf{Y} = \\mathbf{X\\theta}\n",
    "$$\n",
    "一般化的广义线性回归形式是：\n",
    "$$\n",
    "\\mathbf{g}(\\mathbf{Y}) = \\mathbf{X\\theta}\n",
    "$$\n",
    "\n",
    "### 四、正则化\n",
    "\n",
    "#### 4.1 L1正则化   -  Lasso \n",
    "\n",
    "$$\n",
    "J(\\mathbf\\theta) = \\frac{1}{2}(\\mathbf{X\\theta} - \\mathbf{Y})^T(\\mathbf{X\\theta} - \\mathbf{Y}) + \\alpha||\\theta||_1\n",
    "$$\n",
    "\n",
    "Lasso回归的求解办法一般有坐标轴下降法（coordinate descent）和最小角回归法（ Least Angle Regression），\n",
    "\n",
    "\n",
    "\n",
    "#### 4.2 L2正则化   -  Ridge\n",
    "\n",
    "\n",
    "$$\n",
    "J(\\mathbf\\theta) = \\frac{1}{2}(\\mathbf{X\\theta} - \\mathbf{Y})^T(\\mathbf{X\\theta} - \\mathbf{Y}) + \\frac{1}{2}\\alpha||\\theta||_2^2\n",
    "$$\n",
    "\n",
    "Ridge回归的求解比较简单，一般用最小二乘法：\n",
    "$$\n",
    "\\mathbf{\\theta = (X^TX + \\alpha E)^{-1}X^TY}\n",
    "$$\n",
    "\n",
    "### 五、代码练习"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 自己编写的（参考网上）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "class SimpleLinearRegression1:\n",
    "    def __init__(self):\n",
    "        \"\"\"初始化Simple Linear Regression 模型\"\"\"\n",
    "        self.a_ = None\n",
    "        self.b_ = None\n",
    "\n",
    "    def least_square_method(self,X,Y):\n",
    "        theta =  np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), Y)\n",
    "        return theta\n",
    "\n",
    "    def fit(self, x, y):\n",
    "        X0 = np.ones((x.shape[0],1))\n",
    "        x = np.hstack((X0,x))\n",
    "        theta = self.least_square_method(x,y)  # 最小二乘法公式\n",
    "        self.a_ = theta[0]\n",
    "        self.b_ = theta[1]\n",
    "    \n",
    "    def predict(self, x_predict):\n",
    "        \"\"\"给定待预测数据集x_predict， 返回表示x_predict的结果向量\"\"\"\n",
    "\n",
    "        return np.array([self._predict(x) for x in x_predict])\n",
    "\n",
    "    def _predict(self, x_single):\n",
    "        \"\"\"给定单个待预测数据x_single， 返回x_single的预测结果值\"\"\"\n",
    "        return self.a_ + self.b_ * x_single\n",
    "\n",
    "    def __repr__(self):\n",
    "        return \"SimpleLinearRegression1()\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x1bc37efd5c8>]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "X= np.array([1,2,3,4,5]).reshape(-1,1)\n",
    "Y= np.array([1,3,2,3,5])\n",
    "reg = SimpleLinearRegression1()\n",
    "reg.fit(X,Y)\n",
    "\n",
    "y_hat = reg.predict(X)\n",
    "\n",
    "plt.scatter(X,Y)\n",
    "plt.plot(X,y_hat,color = 'orange')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "## 使用官方的API"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Coefficients:  [938.23786125]\n",
      "Mean squared error: 2548.07\n",
      "Coefficient of determination: 0.47\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "from sklearn import datasets, linear_model\n",
    "from sklearn.metrics import mean_squared_error, r2_score\n",
    "\n",
    "# Load the diabetes dataset\n",
    "diabetes_X, diabetes_y = datasets.load_diabetes(return_X_y=True)\n",
    "\n",
    "# Use only one feature\n",
    "diabetes_X = diabetes_X[:, np.newaxis, 2]\n",
    "\n",
    "# Split the data into training/testing sets\n",
    "diabetes_X_train = diabetes_X[:-20]\n",
    "diabetes_X_test = diabetes_X[-20:]\n",
    "\n",
    "# Split the targets into training/testing sets\n",
    "diabetes_y_train = diabetes_y[:-20]\n",
    "diabetes_y_test = diabetes_y[-20:]\n",
    "\n",
    "\n",
    "# Create linear regression object\n",
    "regr = linear_model.LinearRegression()\n",
    "\n",
    "# Train the model using the training sets\n",
    "regr.fit(diabetes_X_train, diabetes_y_train)\n",
    "\n",
    "# Make predictions using the testing set\n",
    "diabetes_y_pred = regr.predict(diabetes_X_test)\n",
    "\n",
    "\n",
    "# The coefficients\n",
    "print('Coefficients: ', regr.coef_)\n",
    "# The mean squared error\n",
    "print('Mean squared error: %.2f'% mean_squared_error(diabetes_y_test, diabetes_y_pred))\n",
    "# The coefficient of determination: 1 is perfect prediction\n",
    "print('Coefficient of determination: %.2f'% r2_score(diabetes_y_test, diabetes_y_pred))\n",
    "\n",
    "\n",
    "\n",
    "# Plot outputs\n",
    "plt.scatter(diabetes_X_test, diabetes_y_test,  color='black')\n",
    "plt.plot(diabetes_X_test, diabetes_y_pred, color='blue', linewidth=3)\n",
    "\n",
    "plt.xticks(())\n",
    "plt.yticks(())\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
